package com.myrpc.proxy;

import com.myrpc.annotation.MyRpcClient;
import com.myrpc.transfer.dto.RpcRequest;
import com.myrpc.transfer.dto.RpcResponse;
import com.myrpc.transfer.transport.RpcRequestTransport;
import com.myrpc.transfer.transport.socket.SocketRpcRequestClient;
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.UUID;

/**
 * 远程方法执行调用拦截器
 */
@Slf4j
public class RemoteMethodInterceptor implements MethodInterceptor {
    /**
     * 用于指定Rpc请求的发送方式
     */
    private RpcRequestTransport rpcRequestTransport;

    public RemoteMethodInterceptor(RpcRequestTransport rpcRequestTransport) {
        this.rpcRequestTransport = rpcRequestTransport;
    }

    /**
     *
     * @param o             被代理对象
     * @param method        被拦截方法
     * @param objects       方法参数
     * @param methodProxy   用于调用原始方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //调用前
        log.info("invoked method: {}", method.getName());
        //获得要调用的目标微服务
        if (o.getClass().getAnnotation(MyRpcClient.class) == null){
            throw new RuntimeException("MyRpc客户端没有配置'MyRpcClient'注解！");
        }
        MyRpcClient myRpcClient = o.getClass().getAnnotation(MyRpcClient.class);
        String targetService = myRpcClient.targetService();
        if (targetService == null || targetService.equals("") || targetService.trim().equals("")){
            throw new RuntimeException(o.getClass().getName() + "没有配置目标微服务或格式非法");
        }
        targetService = targetService.trim();
        //获得接口名称
        String[] splitOfClassName = o.getClass().getName().split("\\.");
        String interfaceName = splitOfClassName[splitOfClassName.length - 1];
        //创建一个RPC请求
        RpcRequest rpcRequest = RpcRequest.builder()
                .interfaceName(interfaceName)
                        .methodName(method.getName())
                                .parameters(objects)
                                        .paramTypes(method.getParameterTypes())
                                                .requestId(UUID.randomUUID().toString())
                                                    .serviceName(targetService).build();
        //发送Rpc请求
        RpcResponse<Object> response = null;
        if (rpcRequestTransport instanceof SocketRpcRequestClient){
            //使用Socket发送
             response = (RpcResponse<Object>) rpcRequestTransport.sendRpcRequest(rpcRequest);
        }else {
            throw new RuntimeException("没有合适的网络传输协议！");
        }
        //调用原方法
//        methodProxy.invokeSuper(o, objects);
        check(rpcRequest, response);
        return response.getData();
    }

    /**
     * 校验发出请求和返回结果是否合法
     * TODO 待编写
     * @param rpcRequest rpc请求
     * @param rpcResponse rpc结果
     */
    private void check(RpcRequest rpcRequest, RpcResponse<?> rpcResponse){

    }
}
